/* 
Scenic Graphics Library
Copyright (C) 2007 Jouni Tulkki

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USApackage scenic;
*/

package scenic;

import java.awt.Rectangle;
import java.awt.geom.AffineTransform;

import scenic.jni.Renderer;

/**
 * This class is used to render a scene graph to an image. The rendering
 * does not take place automatically, instead, the render() method must
 * be called to do the rendering.
 */
public class ImageRenderer implements SceneParent {
	private ScenicImage image;
	private SceneNode scene;
	private ScenicColor bgColor = new ScenicColor(0.0f, 0.0f, 0.0f);
	
	/**
	 * Creates a new ImageRenderer object. Note that the scene is not
	 * rendered automatically. Use the render() method to do the
	 * rendering.
	 * 
	 * @param image the image that is used as the rendering target
	 * @param scene the scene that is rendered to the image.
	 */
	public ImageRenderer(ScenicImage image, SceneNode scene) {
		this.image = image;
		this.scene = scene;
	}
	
	/**
	 * Sets the background color for the image. The background
	 * color is used to clear the image before it is rendered.
	 * Settings the background color to null will disable clearing
	 * of the image. This is useful if you want to do incremental
	 * drawing. The default background color is black.
	 * 
	 * @param color the background color
	 */
	public void setBgColor(ScenicColor color) {
		bgColor = color;
	}

	/**
	 * Gets the current background color.
	 * 
	 * @return the background color
	 */
	public ScenicColor getBgColor() {
		return bgColor;
	}
	
	/**
	 * Gets the scene that is used for rendering.
	 * 
	 * @return the scene
	 */
	public SceneNode getScene() {
		return scene;
	}
	
	/**
	 * Renders the scene to the image. 
	 */
	public void render() {
		if(image.getId() == 0 || image.getWidth() == 0 || image.getHeight() == 0)
			throw new IllegalStateException();
		DrawContext context = new DrawContext();
		Rectangle bounds = new Rectangle(0, 0, image.getWidth(), image.getHeight());
		
		context.root = this;
		context.renderingInstance = new Object();
		context.width = image.getWidth();
		context.height = image.getHeight();
		context.renderer = new Renderer();
		context.context = context.renderer.createContextForImage(image.getId());
		
		context.renderer.enterCriticalSection();
		try {
			if(!context.renderer.beginScene(context.context)) {
				System.out.println("beginScene failed");
				return;
			}

			if(bgColor != null) {
				context.renderer.color(context.context, bgColor);
				context.renderer.clear(context.context);
			}
			if(scene != null) {
				scene.prepareDraw(context, new AffineTransform());
				scene.draw(context, new AffineTransform(), bounds);
			}

			context.renderer.endScene(context.context);
//			context.renderer.present(context.context);
		} finally {
			context.renderer.deleteContext(context.context);
			context.renderer.leaveCriticalSection();			
		}
	}
	
	/**
	 * Automatically called when the image changes. Do not call this 
	 * method yourself.
	 */
	public void childChanged(Rectangle area) {
	}
}
